﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Collections;
using System.Xml;

namespace DictTrans
{
    public partial class Form1 : Form
    {
        private string rootPath = string.Empty;
        private DataSet dsBuffer = new DataSet();
        private bool isFiltered = false;

        public Form1()
        {
            InitializeComponent();
            tsSaveRex.Enabled = false;
        }

        private void btnOpen_Click(object sender, EventArgs e)
        {
            if (fbdTree.ShowDialog() == DialogResult.OK)
            {
                dirTree.Nodes.Clear();
                txtDir.Text = fbdTree.SelectedPath;
                string[] path = txtDir.Text.Split('\\');
                rootPath = fbdTree.SelectedPath;    //.Replace(path[path.Length - 1], "");
                TreeNode root = new TreeNode();
                root.Text = "";
                getTree(txtDir.Text, ref root);
                dirTree.Nodes.Add(root);
            }
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("FileName");
            dt.Columns.Add("Key");
            dt.Columns.Add("BaseValue");
            dt.Columns.Add("Japanese");
            dt.Columns.Add("Chinese");

            bgWork.RunWorkerAsync(dt);
            procBar.Value = 0;
        }

        private void dirTree_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (e.Node.GetNodeCount(true) == 0)
            {
                string filePath = rootPath + e.Node.FullPath;
                DataTable dt = new DataTable();
                dt.Columns.Add("Key");
                dt.Columns.Add("BaseValue");
                dt.Columns.Add("Japanese");
                dt.Columns.Add("Chinese");
                readResx(filePath, ref dt);
                gvData.DataSource = dt;
                tsSaveRex.Enabled = true;
            }
        }

        /// <summary>
        /// make treenodecollection of selected folder
        /// </summary>
        /// <param name="path">selected folder path(root)</param>
        /// <param name="node">treenode will be root</param>
        private void getTree(string path, ref TreeNode node)
        {
            string[] subdirs = Directory.GetDirectories(path);
            string[] files = Directory.GetFiles(path);

            foreach (string file in files)
            {
                TreeNode tn = new TreeNode();
                string[] fname = file.Split('\\');
                tn.Text = fname[fname.Length - 1].Replace(".resx","");
                if (tn.Text.Contains("ja") || tn.Text.Contains("zh-CN"))
                {
                    continue;
                }
                //if (chkXSL.Checked && tn.Text.Contains("XLS_"))
                //{
                //    continue;
                //}
                node.Nodes.Add(tn);
            }

            foreach (string dir in subdirs)
            {
                TreeNode tn = new TreeNode();
                string[] fname = dir.Split('\\');
                tn.Text = fname[fname.Length - 1];
                node.Nodes.Add(tn);
                getTree(dir, ref tn);
            }
        }

        private void readResx(string path, ref DataTable dt)
        {
            XmlDocument xdo = new XmlDocument();

            // read main resx
            xdo.Load(path + ".resx");

            XmlNodeList xnl = xdo.GetElementsByTagName("data");
            foreach (XmlNode xn in xnl)
            {
                if (xn.Attributes["xml:space"] != null && 
                    xn.Attributes["xml:space"].Value.Equals("preserve") &&
                    !xn.Attributes["name"].Value.Contains(">>"))
                {
                    DataRow dr = dt.NewRow();

                    if (dt.Columns.Contains("FileName"))
                    {
                        dr["FileName"] = path;
                    }

                    dr["key"] = xn.Attributes["name"].Value;
                    dr["baseValue"] = getNodeValue(xn);
                    dt.Rows.Add(dr);
                }
            }

            // read japan resx
            xdo.Load(path + ".ja.resx");

            xnl = xdo.GetElementsByTagName("data");
            foreach (XmlNode xn in xnl)
            {
                if (xn.Attributes["xml:space"] != null &&
                    xn.Attributes["xml:space"].Value.Equals("preserve"))
                {
                    DataRow[] drs = dt.Select("Key = '" + xn.Attributes["name"].Value + "'");
                    foreach (DataRow dr in drs)
                    {
                        dr["japanese"] = getNodeValue(xn);
                    }
                }
            }

            // read china resx
            xdo.Load(path + ".zh-CN.resx");

            xnl = xdo.GetElementsByTagName("data");
            foreach (XmlNode xn in xnl)
            {
                if (xn.Attributes["xml:space"] != null &&
                    xn.Attributes["xml:space"].Value.Equals("preserve"))
                {
                    DataRow[] drs = dt.Select("Key = '" + xn.Attributes["name"].Value + "'");
                    foreach (DataRow dr in drs)
                    {
                        dr["chinese"] = getNodeValue(xn);
                    }
                }
            }
        }

        private string getNodeValue(XmlNode xn)
        {
            if (!xn.HasChildNodes)
            {
                return "Error";
            }

            foreach (XmlNode child in xn.ChildNodes)
            {
                if (child.NodeType == XmlNodeType.Element)
                {
                    return child.InnerText;
                }
            }

            return null;
        }

        private void getFiles(TreeNode root, ref ArrayList files)
        {
            foreach (TreeNode tn in root.Nodes)
            {
                if (tn.Nodes.Count > 0)
                {
                    getFiles(tn, ref files);
                }
                else
                {
                    files.Add(rootPath + tn.FullPath);
                }
            }
        }

        private void bgWork_DoWork(object sender, DoWorkEventArgs e)
        {
            //status.Text = "Running...";
            BackgroundWorker worker = (BackgroundWorker)sender;
            DataTable dt = (DataTable)e.Argument;
            ArrayList allFiles = new ArrayList();

            getFiles(dirTree.Nodes[0], ref allFiles);

            //for (int i = 0; i < allFiles.Count; i++)
            for (int i = 0; i < allFiles.Count; i++)
            {
                if (chkXSL.Checked && allFiles[i].ToString().Contains("XLS_"))
                {
                    // continue;
                }
                else
                {
                    readResx(allFiles[i].ToString(), ref dt);
                }
                int progress = (int)((float)i / (float)allFiles.Count * 100);
                worker.ReportProgress(progress);
            }

            e.Result = dt;
        }

        private void bgWork_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            procBar.Value = e.ProgressPercentage;
        }

        private void bgWork_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            procBar.Value = procBar.Maximum;
            DataTable dt = (DataTable)e.Result;
            gvData.DataSource = dt;
            dsBuffer.Tables.Add(dt);
            status.Text = "Completed!";
        }

        private void saveResx(string fileName, DataTable dt)
        {
            Cursor.Current = Cursors.WaitCursor;
            XmlDocument xdo = new XmlDocument();
            xdo.Load(fileName + ".ja.resx");
            XmlNodeList xnl = xdo.GetElementsByTagName("data");

            foreach (XmlNode xn in xnl)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    if (xn.Attributes["xml:space"] != null &&
                        xn.Attributes["xml:space"].Value.Equals("preserve") && 
                        dr["Key"].Equals(xn.Attributes["name"].Value))
                    {
                        setNodeValue(xn, dr["japanese"].ToString());
                    }
                }
            }
            xdo.Save(fileName+".ja.resx");

            xdo.Load(fileName + ".zh-CN.resx");
            xnl = xdo.GetElementsByTagName("data");

            foreach (XmlNode xn in xnl)
            {
                foreach (DataRow dr in dt.Rows)
                {
                    if (xn.Attributes["xml:space"] != null &&
                        xn.Attributes["xml:space"].Value.Equals("preserve") &&
                        dr["Key"].Equals(xn.Attributes["name"].Value))
                    {
                        setNodeValue(xn, dr["chinese"].ToString());
                    }
                }
            }
            xdo.Save(fileName + ".zh-CN.resx");

            tsSaveRex.Enabled = false;
            Cursor.Current = Cursors.Arrow;
        }

        private void saveResx(DataTable dt)
        {
            if (dt.Rows.Count < 1000 && dt.Columns.Contains("FileName"))
            {
                foreach (DataRow dr in dt.Rows)
                {
                    saveResx(dr["FileName"].ToString(), dt);
                }
            }
            else if (!dt.Columns.Contains("FileName"))
            {
                string filePath = rootPath + dirTree.SelectedNode.FullPath;
                saveResx(filePath, dt);
            }
        }

        private void setNodeValue(XmlNode xn, string value)
        {
            if (!xn.HasChildNodes)
            {
                return;
            }

            foreach (XmlNode child in xn.ChildNodes)
            {
                if (child.NodeType == XmlNodeType.Element &&
                    child.Name.ToLower() == "value")
                {
                    child.InnerText = value;
                }
            }
        }

        private void saveToolStripMenuItem_Click(object sender, EventArgs e)
        {
            saveResx(gvData.DataSource as DataTable);
        }

        private void tsSaveRex_Click(object sender, EventArgs e)
        {
            saveResx(gvData.DataSource as DataTable);
        }

        private void gvData_CellEndEdit(object sender, DataGridViewCellEventArgs e)
        {
            tsSaveRex.Enabled = true;
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {
            Research();
        }

        private void Research()
        {
            DataTable dt = dsBuffer.Tables[0];

            if (!string.IsNullOrEmpty(txtKeyword.Text.Trim()))
            {
                gvData.DataSource = dt;
                isFiltered = false;
                return;
            }

            var query = from ndt in dt.AsEnumerable()
                        where ndt.Field<string>("Japanese").Contains(txtKeyword.Text.Trim()) ||
                              ndt.Field<string>("Chinese").Contains(txtKeyword.Text.Trim()) ||
                              ndt.Field<string>("Key").Contains(txtKeyword.Text.Trim()) ||
                              ndt.Field<string>("BaseValue").Contains(txtKeyword.Text.Trim())
                        select ndt;
            DataTable dt1 = query.CopyToDataTable<DataRow>();
            gvData.DataSource = dt1;
            isFiltered = true;
        }
    }
}
